package com.serenegiant.util;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.graphics.SurfaceTexture;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;

import com.serenegiant.usb.IFrameCallback;
import com.serenegiant.usb.Size;
import com.serenegiant.usb.UVCCamera;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * 描述：相机代理类
 */
public class UVCCameraProxy {
    private static final String ACTION_USB_DEVICE_PERMISSION = "ACTION_USB_DEVICE_PERMISSION";

    /*相机预览的默认宽高*/
    private int previewWidth = 640, previewHeight = 480;
    private Context mContext;
    protected UVCCamera mUVCCamera;
    private Surface mSurface;
    private CallBackPreview callBackPreview; // 预览回调
    private UsbManager usbManager;
    /*USB设备打开关闭控制类*/
    private UsbController usbController;
    /*摄像头回调数据的格式  */
    private int pixelFormat = UVCCamera.PIXEL_FORMAT_YUV420SP;

    public UVCCameraProxy(Context context) {
        this.mContext = context;
        this.usbManager = (UsbManager) this.mContext.getSystemService(Context.USB_SERVICE);
    }


    /**
     * 连接usb设备
     *
     * @param usbDevice
     */
    public boolean connectDevice(UsbDevice usbDevice) {
        usbController = new UsbController(usbManager, usbDevice);
        return null != usbController.open();
    }

    /**
     * 关闭usb设备
     */
    private void closeDevice() {
        if (null != usbController) {
            usbController.close();
            usbController = null;
        }
    }

    /**
     * 打开相机
     */
    public boolean openCamera() {
        try {
            mUVCCamera = new UVCCamera();
            mUVCCamera.open(usbController);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 关闭相机
     */
    private void closeCamera() {
        try {
            if (mUVCCamera != null) {
                mUVCCamera.destroy();
                mUVCCamera = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 注销的时候调用
     */
    public void onDestroy() {
        stopPreview();
        closeCamera();
        closeDevice();
    }

    /**
     * 设置相机预览控件，这里封装了相关注册注销广播、检测设备、释放资源等操作
     *
     * @param surfaceView
     */
    public void setPreviewSurface(SurfaceView surfaceView) {
        if (surfaceView != null && surfaceView.getHolder() != null) {
            surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                    mSurface = holder.getSurface();
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                }

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                    mSurface = null;
                    closeCamera();
                }
            });
        }
    }

    /**
     * 设置相机预览控件，这里封装了相关注册注销广播、检测设备、释放资源等操作
     *
     * @param textureView
     */
    public void setPreviewTexture(TextureView textureView) {
        if (textureView != null) {
            textureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
                @Override
                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                    mSurface = new Surface(surface);
                }

                @Override
                public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                }

                @Override
                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                    mSurface = null;
                    closeCamera();
                    return false;
                }

                @Override
                public void onSurfaceTextureUpdated(SurfaceTexture surface) {
                }
            });
        }
    }

    /**
     * 设置相机预览Surface
     *
     * @param surface
     */
    private void setPreviewDisplay(Surface surface) {
        mSurface = surface;
        try {
            if (mUVCCamera != null && mSurface != null) {
                mUVCCamera.setPreviewDisplay(mSurface);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置摄像头的成像亮度
     *
     * @param brightness
     */
    public void setBrightness(int brightness) {
        if (null != mUVCCamera) {
            mUVCCamera.setBrightness(brightness);
        }
    }

    /**
     * 获取当前摄像头的成像亮度
     *
     * @return
     */
    public int getBrightness() {
        if (null != mUVCCamera) {
            return mUVCCamera.getBrightness();
        }
        return 0;
    }

    /**
     * 重置摄像头的成像亮度
     */
    public void resetBrightness() {
        if (null != mUVCCamera) {
            mUVCCamera.resetBrightness();
        }
    }

    /**
     * 设置摄像头的对比度
     *
     * @param contrast
     */
    public void setContrast(final int contrast) {
        if (null != mUVCCamera) {
            mUVCCamera.setContrast(contrast);
        }
    }

    /**
     * 获取当前摄像头对比度的值
     */
    public void getContrast() {
        if (null != mUVCCamera) {
            mUVCCamera.getContrast();
        }
    }

    /**
     * 重置摄像头对比度
     */
    public void resetContrast() {
        if (null != mUVCCamera) {
            mUVCCamera.resetContrast();
        }
    }

    /**
     * 设置摄像头回调数据格式
     *
     * @param pixelFormat 格式
     */
    public void setPiselFormat(int pixelFormat) {
        this.pixelFormat = pixelFormat;
    }

    private static ThreadLocal<byte[]> byteThreadLocal = new ThreadLocal<>();

    /**
     * 开始预览
     */
    public void startPreview(int previewWidth, int previewHeight) {
        try {
            if (mUVCCamera != null) {
                // 图片预览流回调
                mUVCCamera.setFrameCallback(new IFrameCallback() {
                    @Override
                    public void onFrame(ByteBuffer frame) {
                        if (callBackPreview != null) {
                            int len = frame.capacity();
                            byte[] bytesLocal = byteThreadLocal.get();
                            if (null == bytesLocal || len != bytesLocal.length) {
                                bytesLocal = new byte[len];
                                byteThreadLocal.set(bytesLocal);
                            }
                            frame.get(bytesLocal);
                            callBackPreview.onPreviewFrameCallBack(bytesLocal);
                        }
                    }
                }, this.pixelFormat);

                mUVCCamera.setPreviewSize(previewWidth, previewHeight);
                setPreviewDisplay(mSurface);
                mUVCCamera.updateCameraParams();
                mUVCCamera.startPreview();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 停止预览
     */
    public void stopPreview() {
        try {
            if (mUVCCamera != null) {
                mUVCCamera.setButtonCallback(null);
                mUVCCamera.setFrameCallback(null, 0);
                mUVCCamera.stopPreview();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否已经打开相机
     *
     * @return
     */
    public boolean isCameraOpen() {
        return mUVCCamera != null;
    }

    /**
     * 申请打开usb设备权限
     *
     * @param usbDevice
     */
    public boolean requestPermission(UsbDevice usbDevice) {
        if (usbManager.hasPermission(usbDevice)) {
            return true;
        } else {
            PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_DEVICE_PERMISSION), 0);
            usbManager.requestPermission(usbDevice, pendingIntent);
            return false;
        }
    }

    /**
     * 设置预览回调
     *
     * @param callback
     */
    public void setCallBackPreview(CallBackPreview callback) {
        this.callBackPreview = callback;
    }


    /**
     * 获取相机预览尺寸
     *
     * @return
     */
    public Size getPreviewSize() {
        try {
            if (mUVCCamera != null) {
                return mUVCCamera.getPreviewSize();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取相机支持的预览尺寸
     *
     * @return
     */
    public List<Size> getSupportedPreviewSizes() {
        try {
            if (mUVCCamera != null) {
                return mUVCCamera.getSupportedSizeList();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<>();
    }


    /**
     * 获取usb摄像头设备
     *
     * @return
     */
    public List<UsbDevice> getUsbCameraDevice() {
        HashMap<String, UsbDevice> deviceMap = usbManager.getDeviceList();
        if (deviceMap != null) {
            List<UsbDevice> list = new ArrayList<>();
            for (UsbDevice usbDevice : deviceMap.values()) {
                if (isUsbCamera(usbDevice)) {
                    list.add(usbDevice);
                }
            }
            return list;
        }
        return null;
    }

    /**
     * 判断某usb设备是否摄像头，usb摄像头的大小类是239-2
     *
     * @param usbDevice
     * @return
     */
    private boolean isUsbCamera(UsbDevice usbDevice) {
        return usbDevice != null && 239 == usbDevice.getDeviceClass() && 2 == usbDevice.getDeviceSubclass();
    }


    /**
     * usb插拔广播监听类
     */
    private class USBReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
            if (!isUsbCamera(usbDevice)) {
                return;
            }
            switch (intent.getAction()) {
                case ACTION_USB_DEVICE_PERMISSION:
                    boolean granted = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false);
                    break;
                default:
                    break;
            }
        }
    }
}
